﻿using System.Collections.Generic;
using DDotNet.ORM.DataFactory.Enum;
using DDotNet.ORM.DataFactory.Interface;

namespace DDotNet.ORM.DataFactory
{
    /// <summary>
    /// Internal CRUD Helper
    /// </summary>
    internal sealed class CRUDHelper
    {
        #region Constructor

        private CRUDHelper()
        {
        }

        public CRUDHelper(bool useTransaction)
        {
            this._UseTransaction = useTransaction;
        }

        #endregion

        #region Fields

        internal Dictionary<string, IDataBaseFactory> _DataBaseFactories = new Dictionary<string, IDataBaseFactory>();
        private bool _UseTransaction;

        #endregion

        #region Methods

        /// <summary>
        /// Realiza um Rollback em Todas as Transações
        /// </summary>
        public void RollbackTransaction()
        {
            foreach (KeyValuePair<string, IDataBaseFactory> pair in _DataBaseFactories)
            {
                if (this._UseTransaction)
                {
                    pair.Value.RollbackTransactionContext();
                }
                
                pair.Value.CloseConnection();
            }
        }

        /// <summary>
        /// Realiza um Commit em Todas as Transações
        /// </summary>
        public void CommitTransaction()
        {
            foreach (KeyValuePair<string, IDataBaseFactory> pair in _DataBaseFactories)
            {
                if (this._UseTransaction)
                {
                    pair.Value.CommitTransationContext();
                }

                pair.Value.CloseConnection();
            }
        }

        /// <summary>
        /// Retorna uma DataBase Factory
        /// </summary>
        /// <param name="connectionString">Chave da String de Conexão</param>
        /// <returns></returns>
        public IDataBaseFactory GetDataBaseFactory(string connectionString)
        {
            // Verifica se não está no Cache
            if (!this._DataBaseFactories.ContainsKey(connectionString))
            {
                lock (this)
                {
                    // Realiza Nova Verificação
                    if (!this._DataBaseFactories.ContainsKey(connectionString))
                    {
                        // Cria Objetos
                        IDataBaseFactory factory = DataBaseFactory.Instance.GetDataBaseFactory(connectionString);

                        // Inicializa Transação
                        factory.InitializeConnection(this._UseTransaction
                                                         ? TransactionContext.SmartTransaction
                                                         : TransactionContext.TransactionFree);

                        // Adiciona no Cache
                        this._DataBaseFactories.Add(connectionString,
                                                    factory);
                    }
                }
            }

            // Retorna do Cache
            return this._DataBaseFactories[connectionString];
        }

        /// <summary>
        /// Retorna uma DataBase Factory Nova Sem Transação e Fora do Cache
        /// </summary>
        /// <param name="connectionString">Chave da String de Conexão</param>
        /// <returns></returns>
        public IDataBaseFactory GetNewNoCacheTransactionLeddDataBaseFactory(string connectionString)
        {
            // Cria Objetos
            IDataBaseFactory factory = DataBaseFactory.Instance.GetDataBaseFactory(connectionString);

            // Inicializa Transação
            factory.InitializeConnection(TransactionContext.TransactionFree);

            // Retorna 
            return factory;
        }

        #endregion
    }
}